local nl = require'luaNumeric'
local math = require'math'
local unity = require "luaUnity"
--local GLUI = require"luaGLShapes"
require("lfs")

--==============================================================================================================--
--设置默认参数
local CSSModule=require"luaSAR"
local SAR = CSSModule.SAR;
--==============================================================================================================--

--===========================================================================--
--创建表和创建元表
function SAR:init ()
	self.results = {};	
	--self.set_settings_str = Gallop.set_settings_str;
	--self.get_settings_str = Gallop.get_settings_str;
	
	--self:regist_funcs_to_gallop();
	--self.init_strs = self:get_settings_str();
	--self:get_settings_str();
end
--===========================================================================--


--===========================================================================--
--注册全局函数
function SAR:regist_funcs_to_gallop()
	Gallop.init_funcs['SARApp'] = function()
		local str = self.init_strs;
		assert( type('str')=='string', 'SARApp Plugin init string error' );
		if str ~= '' then
			Gallop.SARApp:set_settings_str(str)
		end
		Gallop.SARApp:update_parameters_to_ui();
	end;
	
	Gallop.load_funcs['SARApp'] = function()
		local str = Geometry.get_setting( 'SARApp.Settings' )
		if str ~= '' then
			Gallop.SARApp:set_settings_str(str)
		end
		Gallop.SARApp:update_parameters_to_ui();
		Gallop.SARApp:init_parameters()
	end;
	
	Gallop.presave_funcs['SARApp'] = function()
		Gallop.SARApp:update_parameters_from_ui()
		local str = Gallop.SARApp:get_settings_str();
		Geometry.set_setting( 'SARApp.Settings', str );
	end;
end
--===========================================================================--


--===========================================================================--
-- 保存和读取函数
function SAR:set_settings_str(str)
	Gallop.set_settings_str(self,str);
	self.results = undump_t(self.strResults);
	self.strResults = nil;
end

function SAR:get_settings_str()
	--abc = getmetatable(self)
	--for k,v in pairs (abc) do 
		--print(k,v);
	--end
	--print(abc,abc.results)
	--self.strResults = dump_t(self.results,'');
	--local str = Gallop.get_settings_str(self);
	--self.strResults = nil;
	--return str;
	return 'a';
end
--===========================================================================--


--==============================================================================================================--
--SAR成像计算
function SAR:get_fields()
	return self.fields;
end
--==============================================================================================================--

--===========================================================================--
--ui交互函数:设置参数按钮
function SAR:get_shape(objs)
	return self.shape:copy();
end
--===========================================================================--

--===========================================================================--
--ui交互函数:设置参数按钮
function SAR:get_range()
	return self.range_min,self.range_max,self.auto_range;
end
--===========================================================================--

--===========================================================================--
--ui交互函数:设置参数按钮
function SAR:update_range()
	if self.fields then  
		if self.auto_range then 
			self.range_min,self.range_max = self.fields:value_range();
		end
	end
	self:update_range_to_view();
	self:update_range_to_ui();
	self:update_view();
end
--===========================================================================--

--===========================================================================--
--ui交互函数:设置参数按钮
function SAR:change_view_range(min,max,bset)
	self.range_min,self.range_max,self.auto_range = min,max,bset;
	self:update_range()
end
--===========================================================================--

--===========================================================================--
--ui交互函数:刷新区间
function SAR:refresh_range()
	if self.fields then  
		self.range_min,self.range_max = self.fields:value_range();
	end
	self:update_range()
end
--===========================================================================--

--==============================================================================================================--
--更新SBR求解器参数
function SAR:update_solver_settings()

	--读取SAR界面设置参数
	self:update_parameters_from_ui();	
	--print( self.x_range )
	--print( self.y_range )
	--print( self.resolution )
	--print( self.center_freq )
	--print( self.center_theta )
	local light_speed = 299792458
	local freq_width = ((light_speed/(2*self.resolution*1e-3))*1e-9)
	print(self.is_imaging_2D)
	local a=nil
	local df = freq_width/2;
	local f = self.center_freq;
	local nf ,uneed = math.modf(self.x_range/self.resolution);
	self.nf = nf
	if freq_width*10 > self.center_freq then
	      print('带宽为',freq_width..'GHz','中心频率小于10倍要求带宽，可能导致成像精度不足！')
	      a=1
	end
	if self.center_freq-freq_width/2<0 then
	    print('所需成像分辨率过大，目前中心频率无法支持要求带宽！')
	    a=1
	end
	
	
	Gallop.SBRApp.bFreqList = true;
	Gallop.SBRApp.freqList = '(' .. f-df .. ',' .. f+df .. ',' .. nf .. ')' ;
	
	local theta_width = light_speed/(2*self.center_freq*1e9*self.resolution*1e-3)/2
	local dt = theta_width*180/pi;
	local t = self.center_theta;
	local nt  = nf;
	self.nt = nt
	if dt*2>=6 then
	    print('角度宽为',(dt*2)..'°','成像扫描角度大于6°，可能导致成像精度不足！')
	    a=1
	end
	
	if a then
	    print('存在影响成像精度的设置，是否选择继续成像！')
	else
	    print('可以实现良好成像')
	end
	
	Gallop.SBRApp.bThetaList = true;
	Gallop.SBRApp.thetaList = '(' .. t-dt .. ',' .. t+dt .. ',' .. nt .. ')' ;
	if self.is_imaging_2D==false then
	    Gallop.SBRApp.thetaList = tostring(t) ;
	end
	
	
	Gallop.SBRApp.minPhi = 0;
	Gallop.SBRApp.maxPhi = 0;
	Gallop.SBRApp.numPhi = 1;

	--更新界面参数
	Gallop.SBRApp:update_parameters_to_ui();
	Gallop.SBRApp:create_calculation_model()
	

	
end
--==============================================================================================================--

--==============================================================================================================--
--SAR成像计算
function SAR:calculate()
	Gallop.SBRApp:run_pond()
        self.shape = Gallop.SBRApp.shape:copy();
	if self.is_imaging_2D then
	    self:calculate_sar()
	    self.fields=self:create_fields();
	    self:plot2D()	
	    ---------更新画图区域
	    self:update_border_to_ui();
	   -------更新场分布
	    self:update_fields();
	   ------更新形状
	    self:update_shape();
	    self:update_range();
	else
	    self:calculate_1D()
	    self:plot1D()
	    self.fields=self:create_fields();
	    ---------更新画图区域
	    self:update_border_to_ui();
	   -------更新场分布
	    self:update_fields();
	   ------更新形状
	    self:update_shape();
	
	end

	
	--self:calculate_sar()
	--self.fields=self:create_fields();
	--self:plot1D()
	--print(self.is_imaging_2D)
        --if self.is_imaging_2D then
	    --self:plot2D()	
	    --
	    	--
	---------更新画图区域
	    --self:update_border_to_ui();
	---------更新场分布
	    --self:update_fields();
	--------更新形状
	    --self:update_shape();
	--end
	--self:plot1D()
	-------更新画图区域
	--self:update_border_to_ui();
	-----更新场分布
	--self:update_fields();
	----更新形状
	--self:update_shape();
end
--==============================================================================================================--
--==============================================================================================================--
--SAR成像计算
function SAR:get_fields()
	return self.fields;
end
--==============================================================================================================--

--===========================================================================--
--ui交互函数:设置参数按钮
function SAR:get_shape(objs)
	return self.shape:copy();
end
--===========================================================================--
function SAR:plot2D()
    local xposition = self.xposition
    local yposition = self.yposition
    local ISAR = self.ISAR
    local fields = self:create_fields();
	for ii=1,#yposition do
	    for jj=1,#xposition do
	        if nl.abs(xposition[ii][jj])*1e3<=self.x_range/2 and nl.abs(yposition[ii][jj]*1e3)<=self.y_range/2 then
		    theta_need = self.center_theta*pi/180;
		    xposition_need = xposition[ii][jj]*nl.cos(theta_need)-nl.sin(theta_need)*yposition[ii][jj]
		    yposition_need = xposition[ii][jj]*nl.sin(theta_need)+nl.cos(theta_need)*yposition[ii][jj]
		    --fields:insert(1e3*xposition[ii][jj],1e3*yposition[ii][jj],0,ISAR[ii][jj])
		    fields:insert(1e3*xposition_need,1e3*yposition_need,0,ISAR[ii][jj])
		end
	    end
	end
    self.fields = fields;
end
--=================================================================================================
function SAR:calculate_1D()
	local need_RCS = Gallop.SBRApp.RCS
	local need_freq = Gallop.SBRApp.probe_freq
	local light_speed = 299792458
	local index_freq = #need_freq/(#need_freq-1)

	--------构建计算ISAR矩阵
	local Es_matrix = nl.new_eigen_cmatrix(#need_freq,1)
	Es_matrix:set_zero()
	local tmp=0

       for j=1,#need_freq do
		tmp = need_RCS[{1,1,j,1}]
		Es_matrix[{j,1}] =tmp
      end

      local freq_need = nl.new_eigen_cmatrix(#need_freq,#need_freq)
      local need_x = nl.LinearSpace(-1*1e-3*self.x_range/2,1e-3*self.x_range/2,self.nf)

      for i=1,#need_freq do
          for j=1,#need_freq do
	        index = 2 * pi * (  2 *  (  need_freq[j] * 1e9 / light_speed )  ) * need_x[i]
		index = nl.new_complex(0,index)
		freq_need[{i,j}] = nl.exp(-1*index)
	  end
      end

      local ISAR = freq_need * Es_matrix
      local ISAR_abs=nl.new_vector(#need_freq)
      
      for i=1,#need_freq do
          ISAR_abs[i] =  nl.abs(ISAR[{i,1}])
      end
      
      local tmp_max = 0
      for i=1,#ISAR_abs do
          if ISAR_abs[i]>=tmp_max then
	      tmp_max = ISAR_abs[i]
	  end
      end
      
      for i=1,#need_freq do
          ISAR_abs[i] =  ISAR_abs[i]/tmp_max
      end
      
      self.x_need = need_x
      self.ISAR_1D = ISAR_abs
      
end
----=============--
function SAR:plot1D()
     local view = self.view1D;
     self.view1D:clearGraphs();
     local gp = view:addGraph(self.x_need,self.ISAR_1D,'center freq='..tostring(self.center_freq)..'GHz'..' center theta='..tostring(self.center_theta)..'°');
end
--=======================================-
function SAR:calculate_sar()
        
	local need_RCS = Gallop.SBRApp.RCS
	local need_freq = Gallop.SBRApp.probe_freq
	local need_theta = Gallop.SBRApp.theta_angles
	local light_speed = 299792458
	local freq_center=self.center_freq
	local index_freq = #need_freq/(#need_freq-1)
	local index_theta = #need_theta/(#need_theta-1)
	local wave_center = 2 * pi * freq_center / light_speed
	local dx = light_speed/(2*(need_freq[#need_freq]-need_freq[1])*index_freq*1e9)
	local dy = light_speed/(2*1e9*freq_center*(need_theta[#need_theta]-need_theta[1])*index_theta*(pi/180))
	--------构建计算ISAR矩阵
	local Es_matrix = nl.new_eigen_cmatrix(#need_theta,#need_freq)
	Es_matrix:set_zero()
	local tmp=0
	for i=1,#need_theta do
	    for j=1,#need_freq do
	        --tmp = 10^(need_RCS[{i,j,1,p}]/10)
		tmp = need_RCS[{i,1,j,1}]
		Es_matrix[{i,j}] =tmp
	    end
	end


	local need_y = nl.LinearSpace(-1*1e-3*self.y_range/2,1e-3*self.y_range/2,self.nt)
	---------------------------构建方位向变化矩阵
	local index=0
	local theta_change=nl.new_eigen_cmatrix(#need_theta,#need_theta)
	theta_change:set_zero()
	for i=1,#need_theta do
	    for j=1,#need_theta do
	        index = 2 * pi * ( wave_center * 1e9 * need_theta[j] * pi / ( 180 * pi ) ) * need_y[i]
		index = nl.new_complex(0,index)
		theta_change[{i,j}] = nl.exp(-1*index)
		
	    end
	end
	-------------------------构建完成
	
	local need_x = nl.LinearSpace(-1*1e-3*self.x_range/2,1e-3*self.x_range/2,self.nf)
	------------------------构建距离向变化矩阵
	local freq_change = nl.new_eigen_cmatrix(#need_freq,#need_freq)
	freq_change:set_zero()
	for i=1,#need_freq do
	    for j=1,#need_freq do
	        index = 2 * pi * (  2 *  (  need_freq[i] * 1e9 / light_speed )  ) * need_x[j]
		index = nl.new_complex(0,index)
		freq_change[{i,j}] = nl.exp(-1*index)
	    end
	end
	------------------构建完成
	

	------------进行傅里叶变化
	local first_change = theta_change * Es_matrix
	local ISAR = first_change * freq_change
	------------构建振幅结果
	local ISAR_abs={}
	for i=1,#need_theta do
	    ISAR_abs[i] = nl.new_vector(#need_freq)
	end
	
	for i=1,#need_theta do
	    for j=1,#need_freq do
	        ISAR_abs[i][j]  = nl.abs(ISAR[{i,j}])
	    end
	end
		
	-----------进行ifftshift操作完成正常矩阵

	--------------归一化计算
	local tmp_max = 0
        for k,v in pairs(ISAR_abs) do
	    for k1,v1 in pairs(v) do
	          if v1>= tmp_max then
		      tmp_max = v1
		  end
	    end
	end
	--print(tmp_max)
	-----------归一化
	for i=1,#need_theta do
	     for j=1,#need_freq do
	         ISAR_abs[i][j] = ISAR_abs[i][j]/tmp_max
	     end
	end
	--
	--
	local xposition={}
	local yposition = {}
	for i=1,#need_theta do
	    xposition[i] = nl.new_vector(#need_x)
	    yposition[i] = nl.new_vector(#need_y)
	end

	for i=1,#need_theta do
	      for j=1,#need_freq do
		  xposition[i][j] = need_x[j]
	      end
	end
	
	for jj=1,#need_freq do
	      for ii=1,#need_theta do
		    yposition[ii][jj] = need_y[ii]
	      end
	end
	
	self.xposition = xposition
	self.yposition = yposition
	self.ISAR = ISAR_abs
	print('成像计算完成') 
end
--==============================================================================================================--
--===========================================================================--
--ui交互函数:设置参数按钮
function SAR:get_border()
	self.shape = Gallop.SBRApp.shape;
	if  self.shape then  
		self.shape:build_shape()
		local bbox = self.shape:bbox();
		local xmin = math.min( bbox:xcenter() - self.x_range/2 , bbox:xmin() );
		local xmax = math.max( bbox:xcenter() + self.x_range/2 , bbox:xmax() );
		local ymin = math.min( bbox:ycenter() - self.y_range/2 , bbox:ymin() );
		local ymax = math.max( bbox:ycenter() + self.y_range/2 , bbox:ymax() );		
		return xmin,ymin,bbox:zmin(),xmax,ymax,bbox:zmax();
	end
	return 0,0,0,1,1,1;
end
--===========================================================================--
--ui交互函数:设置参数按钮
function SAR:view_data()
	print( "查看数据")
	--
	--self.viewData = Gallop.DataPost:create_data_table_to_ui();
	local xposition = self.xposition
	local yposition = self.yposition
	local ISAR = self.ISAR
	local data = nl.new_eigen_matrix(#xposition*#yposition,3);
	data:set_zero()
	local header = nl.new_svector();

	header:add('x(mm)')
	header:add('y(mm)')
	header:add('normalize')	
	
	--
	for i=1,#yposition do
	    for j=1,#xposition do
	        data[{(i-1)*#xposition+j,1}]=1e3*xposition[i][j]
		data[{(i-1)*#xposition+j,2}]=1e3*yposition[i][j]
		data[{(i-1)*#xposition+j,3}]=ISAR[i][j]
	    end
	end
	
       self.viewData = Gallop.DataPost:create_data_table_to_ui();
       self.viewData:set_header(header);
       self.viewData:set_data(data);
end
--===========================================================================--


return SAR;